package cn.baker.rabbitmq.sender;

import cn.baker.rabbitmq.entity.TransMessage;
import com.fasterxml.jackson.databind.ObjectMapper;
import cn.baker.rabbitmq.service.TransMessageService;
import com.google.common.base.Throwables;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.transaction.annotation.Transactional;

/**
 * 发送事务消息
 * @author yuanyu
 */
@Slf4j
public class TransMessageSender {

    private final ObjectMapper objectMapper = new ObjectMapper();

    private RabbitTemplate transRabbitTemplate;
    private TransMessageService transMessageService;

    public TransMessageSender(RabbitTemplate transRabbitTemplate, TransMessageService transMessageService) {
        this.transRabbitTemplate = transRabbitTemplate;
        this.transMessageService = transMessageService;
    }

    /**
     * 发送事务消息
     *
     * @param exchange   交换机
     * @param routingKey 路由key
     * @param payload    消息体
     */
    @Transactional(rollbackFor = Exception.class)
    public void convertAndSend(String exchange, String routingKey, Object payload) {
        log.info("@mqLog 开始发送事务消息, exchange:[{}], routingKey:[{}], payload:[{}]", exchange, routingKey, payload);
        try {
            String payloadStr = objectMapper.writeValueAsString(payload);
            // 发送前暂存消息
            TransMessage transMessage = transMessageService.messageSendReady(exchange, routingKey, payloadStr);
            // 设置消息属性
            MessageProperties messageProperties = new MessageProperties();
            messageProperties.setContentType("application/json");
            messageProperties.setMessageId(transMessage.getId());
            Message message = new Message(payloadStr.getBytes(), messageProperties);
            //发送
            transRabbitTemplate.convertAndSend(exchange, routingKey, message, new CorrelationData(transMessage.getId()));
            log.info("@mqLog 发送事务消息成功, 消息ID:[{}]", transMessage.getId());
        } catch (Exception e) {
            log.info("@mqLog 发送事务消息失败, stackTrace:[{}]", Throwables.getStackTraceAsString(e));
            log.error(e.getMessage(), e);
            throw new RuntimeException("发送RabbitMQ消息失败!!!", e);
        }
    }
}
